﻿// CBattleState.cs
// Author: Gant Briseno, Ren Katims
#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Casters.source.Managers;
using Casters.source.Objects;
using Microsoft.Xna.Framework.Input;
using Casters.source.States.UIs;
#endregion

namespace Casters.source.States
{
    public class CBattleState : CBaseState
    {
        public enum BattlePhase { Standby, Move, Combat, Combat_Cast_Phase1, Combat_Cast_Phase2, Combat_Cast_Phase3, Max };

        // Singleton Access
        private static CBattleState instance = null;
        static public CBattleState GetInstance()
        {
            if (instance == null)
                instance = new CBattleState();

            return instance;
        }

        // Variables
        // Players will be dynamic later on
        public CPlayer[] m_Players = new CPlayer[2];
        protected int m_nTurnNum;
        protected SpriteFont m_Font;
        protected Texture2D m_image;

        // The User Interface
        protected CBattleUI m_UI;

        // Current Phase
        protected BattlePhase m_Phase;

        // Used to make sure only one combat phase per turn
        protected bool m_bCombatDone;

        public int GetTurnNum() { return m_nTurnNum; }

        public CBattleState() { }

        /// <summary>
        /// Defaults the state
        /// </summary>
        public override void Initialize()
        {
            CTileManager.GetInstance();

            m_UI = new CBattleUI();
            CUIManager.AddUI(m_UI);

            m_nTurnNum = 0;
            m_Phase = BattlePhase.Standby;
            m_bCombatDone = false;
        }

        /// <summary>
        /// Load all images used within the state
        /// 
        /// Register all events
        /// </summary>
        public override void LoadContent()
        {
            // Tile Manager Initialization, this will change, currently stores the texture itself
            ContentManager loader = new ContentManager(CGame.GetInstance().Services, "Content");

            CTileManager.GetInstance().Initialize(new Vector2(8, 8), new Vector2(320, 266), new Vector2(3, 3), new Color(207, 206, 186), loader.Load<Texture2D>("NewTiles") as Texture2D);
            CTileManager.GetInstance().CreateRandomMap();

            for (int i = 0; i < 2; ++i)
            {
                m_Players[i] = new CPlayer();
                m_Players[i].SetPlayerNumber(i);
                CObjectManager.AddObject(m_Players[i]);
            }

            m_Font = CGame.GetInstance().Content.Load<SpriteFont>("Fonts/Arial");

            m_image = CGame.GetInstance().Content.Load<Texture2D>("Menu/menu_window");

            // Register Events
            CEventSystem.RegisterEventHandler(EventID.Confirm, OnConfirm);
            CEventSystem.RegisterEventHandler(EventID.Back, OnBack);
            CEventSystem.RegisterEventHandler(EventID.BattleUI_MoveClicked, OnMoveUIClicked);
            CEventSystem.RegisterEventHandler(EventID.BattleUI_CombatClicked, OnCombatUIClicked);
            CEventSystem.RegisterEventHandler(EventID.BattleUI_SpellClicked, OnSpellUIClicked);
            CEventSystem.RegisterEventHandler(EventID.BattleUI_EndTurnClicked, OnEndTurn);
            CEventSystem.RegisterEventHandler(EventID.Up, OnMoveUp);
            CEventSystem.RegisterEventHandler(EventID.Down, OnMoveDown);
            CEventSystem.RegisterEventHandler(EventID.Left, OnMoveLeft);
            CEventSystem.RegisterEventHandler(EventID.Right, OnMoveRight);
            CEventSystem.RegisterEventHandler(EventID.Player_Dead, OnPlayerDead);

            CGame.GetInstance().m_Camera.m_bEnabled = true;
        }

        /// <summary>
        /// Unload all data
        /// 
        /// Unregister for all events
        /// </summary>
        public override void UnloadContent()
        {
            CTileManager.GetInstance().Reset();

            for (int i = 0; i < 2; ++i)
                CObjectManager.RemoveObject(m_Players[i]);

            CUIManager.RemoveUI(m_UI);

            m_Font = null;
            m_image = null;

            // Unregister events
            CEventSystem.UnregisterEventHandler(EventID.Confirm, OnConfirm);
            CEventSystem.UnregisterEventHandler(EventID.Back, OnBack);
            CEventSystem.UnregisterEventHandler(EventID.BattleUI_MoveClicked, OnMoveUIClicked);
            CEventSystem.UnregisterEventHandler(EventID.BattleUI_CombatClicked, OnCombatUIClicked);
            CEventSystem.UnregisterEventHandler(EventID.BattleUI_SpellClicked, OnSpellUIClicked);
            CEventSystem.UnregisterEventHandler(EventID.BattleUI_EndTurnClicked, OnEndTurn);
            CEventSystem.UnregisterEventHandler(EventID.Up, OnMoveUp);
            CEventSystem.UnregisterEventHandler(EventID.Down, OnMoveDown);
            CEventSystem.UnregisterEventHandler(EventID.Left, OnMoveLeft);
            CEventSystem.UnregisterEventHandler(EventID.Right, OnMoveRight);
            CEventSystem.UnregisterEventHandler(EventID.Player_Dead, OnPlayerDead);

            CGame.GetInstance().m_Camera.m_bEnabled = false;
        }

        /// <summary>
        /// Runs update logic
        /// </summary>
        /// <param name="dt">Delta Time</param>
        public override void Update(float dt)
        {
        }

        /// <summary>
        /// Renders the battle state
        /// </summary>
        public override void Draw()
        {
            CTileManager.GetInstance().Render();

            Vector2 cameraOffset = CGame.GetInstance().m_Camera.m_vPosition;

            Rectangle rect = new Rectangle(90 + (int)cameraOffset.X, 615 + (int)cameraOffset.Y, 150, 140);
            CRenderEngine.Draw(m_image, rect, Color.Wheat);

            // Debug info since no visual feedback for these phases yet
            CRenderEngine.DrawString(m_Font, "Player " + ((m_nTurnNum % 2) + 1).ToString() + "'s turn", new Vector2(100, 625) + cameraOffset, Color.Black);
            CRenderEngine.DrawString(m_Font, m_Players[m_nTurnNum % 2].GetHealthString(), new Vector2(100, 650) + cameraOffset, Color.Black);
            
            CRenderEngine.DrawString(m_Font, m_Players[m_nTurnNum % 2].GetSuperMeterString(), new Vector2(100, 700) + cameraOffset, Color.Black);
            CRenderEngine.DrawString(m_Font, "Phase: " + m_Phase.ToString(), new Vector2(100, 725) + cameraOffset, Color.Black);
        }

        /*** EVENTS ***/
        /// <summary>
        /// When the backspace key is pressed or cancel button is clicked
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnBack(params object[] eventArgs)
        {
            int playerTurn = m_nTurnNum % 2;

            switch (m_Phase)
            {
                case BattlePhase.Move:
                    m_Phase = BattlePhase.Standby;
                    CTileManager.GetInstance().ResetTileColor();
                    //m_Players[playerTurn].m_vPositionOnMap = m_Players[playerTurn].m_vOldPositionOnMap;
                    
                    m_UI.UnloadReadyCheck();
                    CEventSystem.BroadcastEvent(EventID.TileCursor_Kill);
                    break;
                case BattlePhase.Combat_Cast_Phase1:
                    CTileManager.GetInstance().ResetTileColor();
                    m_Phase = BattlePhase.Combat;
                    m_UI.UnloadReadyCheck();
                    break;
            }
        }

        /// <summary>
        /// When enter key is pressed or confirm button is clicked
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnConfirm(params object[] eventArgs)
        {
            int playerTurn = m_nTurnNum % 2;

            switch (m_Phase)
            {
                case BattlePhase.Move:
                    m_Phase = BattlePhase.Standby;
                    CTileManager.GetInstance().ResetTileColor();
                    m_UI.UnloadReadyCheck();
                    CEventSystem.BroadcastEvent(EventID.TileCursor_Kill);
                    break;
                case BattlePhase.Combat_Cast_Phase1:
                    if (playerTurn == 0)
                        m_Players[1].ModifyHealth(CSpellManager.GetInstance().GetSpell(m_Players[playerTurn].m_nActiveSpell).GetPower());
                    else
                        m_Players[0].ModifyHealth(CSpellManager.GetInstance().GetSpell(m_Players[playerTurn].m_nActiveSpell).GetPower());

                    CTileManager.GetInstance().ResetTileColor();
                    m_UI.UnloadReadyCheck();
                    m_UI.UnloadSpells();
                    m_Phase = BattlePhase.Standby;
                    m_bCombatDone = true;
                    
                    break;
            }
        }

        /// <summary>
        /// Called when the Move button is clicked
        /// Changes to the move phase as long as current player has enough stamina to move
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnMoveUIClicked(params object[] eventArgs)
        {
            int player = m_nTurnNum % 2;
            /*if (m_Players[player].GetStamina() > 0)
            {
                m_Players[player].m_vOldPositionOnMap = m_Players[player].m_vPositionOnMap;
                m_Players[player].SetOldStamina();
                m_Phase = BattlePhase.Move;
                CTileManager.GetInstance().MarkTiles(m_Players[player].m_vPositionOnMap, m_Players[player].GetStamina() * 0.5f + 1, Color.DodgerBlue);
                m_UI.LoadReadyCheck();
                CObjectManager.AddObject(new CTileCursor(m_Players[player].m_vPositionOnMap));
            }*/
        }

        /// <summary>
        /// Called when the Combat button is clicked
        /// Changes the phase to Combat as long as the phase is in standby
        /// and combat hasn't be done yet this turn
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnCombatUIClicked(params object[] eventArgs)
        {
            if (m_Phase == BattlePhase.Standby && !m_bCombatDone)
            {
                m_Phase = BattlePhase.Combat;

                // LoadSpells now takes the player as a parameter
                //m_UI.LoadSpells();
            }
        }

        /// <summary>
        /// Called when a Spell Slot button is clicked
        /// Will add a spell to the cast list for the player that cast it
        /// </summary>
        /// <param name="eventArgs">[0] slot number</param>
        public void OnSpellUIClicked(params object[] eventArgs)
        {
            int spellSlot = (int)eventArgs[0];

            int targetPlayer = m_nTurnNum % 2;

            if (m_Phase == BattlePhase.Combat)
            {
                m_UI.LoadReadyCheck();
                m_Phase = BattlePhase.Combat_Cast_Phase1;
                m_Players[targetPlayer].m_nActiveSpell = m_Players[targetPlayer].m_SpellSlots[spellSlot];
                CTileManager.GetInstance().MarkTilesLoS(m_Players[targetPlayer].m_vPositionOnMap, CSpellManager.GetInstance().GetSpell(m_Players[targetPlayer].m_nActiveSpell).GetRange(), Color.Red, m_Players[targetPlayer].m_vSightDirection);
            }
        }

        /// <summary>
        /// Input was detected to move the player UP
        /// Up Arrow
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnMoveUp(params object[] eventArgs)
        {
            if (m_Phase == BattlePhase.Move)
                CEventSystem.BroadcastEvent(EventID.Move_TileCursorUp);
        }

        /// <summary>
        /// Input was detected to move the player down
        /// Down Arrow
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnMoveDown(params object[] eventArgs)
        {
            if (m_Phase == BattlePhase.Move)
                CEventSystem.BroadcastEvent(EventID.Move_TileCursorDown);
        }

        /// <summary>
        /// Input was detected to move the player Left
        /// Left Arrow
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnMoveLeft(params object[] eventArgs)
        {
            if (m_Phase == BattlePhase.Move)
                CEventSystem.BroadcastEvent(EventID.Move_TileCursorLeft);
        }

        /// <summary>
        /// Input was detected to move the player Right
        /// Right Arrow
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnMoveRight(params object[] eventArgs)
        {
            if (m_Phase == BattlePhase.Move)
                CEventSystem.BroadcastEvent(EventID.Move_TileCursorRight);
        }

        /// <summary>
        /// Called when the End Turn button is clicked
        /// Resets back to start of turn and increments the turn number
        /// </summary>
        /// <param name="eventArgs"></param>
        public void OnEndTurn(params object[] eventArgs)
        {
            if (m_Phase == BattlePhase.Standby)
            {
                ++m_nTurnNum;
                
                m_bCombatDone = false;
            }
        }

        public void OnPlayerDead(params object[] eventArgs)
        {
            int playerDead = (int)eventArgs[0];

            CEventSystem.BroadcastEvent(EventID.ChangeState, CMenuState.GetInstance());
        }
    }
}
